#include "ResourceFileCache.h"

using namespace Stray;
using namespace Stray::Resource;

ResourceFileCache::ResourceFileCache(size_t cacheSize) :
cacheSize_(cacheSize)
{
}

ResFilePtr ResourceFileCache::getFile(const FileID& fileName)
{
	ResFilePtr file = find(fileName);
	if(!file.get())
	{
		file = load(fileName);
	}

	return file;
}

void ResourceFileCache::flush()
{
	while(!resFileMap_.empty())
	{
		ResFilePtr temp = *lruResFileList_.begin();
		free(temp);
	}
}

ResFilePtr ResourceFileCache::find(const FileID& fileName)
{
	ResFileMap::iterator iter;
	iter = resFileMap_.find(fileName);
	if(iter != resFileMap_.end()) return iter->second;
	else return ResFilePtr();
}

ResFilePtr ResourceFileCache::load(const FileID& fileName)
{
	ResFilePtr spResFile;
	
	spResFile = factory_.create(fileName);
	if(!spResFile.get()) return spResFile;

	spResFile->loadData();
	lruResFileList_.push_front(spResFile);
	resFileMap_[fileName] = spResFile;

	size_t check = usedSize_;
	usedSize_ += spResFile->getDataSize();
	assert(check <= usedSize_);
	while(usedSize_ <= cacheSize_)
	{
		freeOneResFile();
	}

	return spResFile;
}

void ResourceFileCache::update(const ResFilePtr& spResFile)
{
	lruResFileList_.remove(spResFile);
	lruResFileList_.push_front(spResFile);
}

void ResourceFileCache::free(const ResFilePtr& spResFile)
{
	if(!spResFile.get()) return;
	lruResFileList_.remove(spResFile);
	resFileMap_.erase(spResFile->getID());

	size_t check = usedSize_;
	usedSize_ -= spResFile->getDataSize();
	assert(check >= usedSize_);
}

void ResourceFileCache::freeOneResFile()
{
	LRUResFileList::iterator gonner = lruResFileList_.end();
	--gonner;

	free(*gonner);
}